package com.sh.data.engine.application.service.datadev;

import cn.hutool.core.convert.Convert;
import com.sh.data.engine.application.model.dto.datadev.OfflineDevCreateTableResponse;
import com.sh.data.engine.application.model.dto.datadev.OfflineDevPreviewDataResponse;
import com.sh.data.engine.application.model.dto.datadev.OfflineDevSyncResponse;
import com.sh.data.engine.application.model.dto.integration.OfflineSyncDatabaseResponse;
import com.sh.data.engine.application.model.dto.integration.OfflineSyncTablesResponse;
import com.sh.data.engine.application.model.dto.integration.OfflineTaskExistTableMappingResponse;
import com.sh.data.engine.application.model.mapper.datadev.OfflineDevSyncResponseMapper;
import com.sh.data.engine.application.model.request.datadev.OfflineDevSyncRequest;
import com.sh.data.engine.application.model.request.integration.OfflineTaskExistTableMappingRequest;
import com.sh.data.engine.common.util.ServletUtils;
import com.sh.data.engine.domain.base.model.UserContext;
import com.sh.data.engine.domain.dataasset.service.TblPropService;
import com.sh.data.engine.domain.datadev.offline.model.domain.OfflineDevSyncDomain;
import com.sh.data.engine.domain.datadev.offline.service.DatadevJobService;
import com.sh.data.engine.domain.datadev.offline.service.OfflineDevMenuNodeService;
import com.sh.data.engine.domain.integration.datasource.model.domain.DataSourceCreateTableDomain;
import com.sh.data.engine.domain.integration.datasource.service.DataSourceService;
import com.sh.data.engine.domain.integration.offline.model.domain.OfflineSyncDatabaseDomain;
import com.sh.data.engine.domain.integration.offline.model.domain.OfflineSyncTableDomain;
import com.sh.data.engine.domain.integration.offline.model.domain.OfflineTaskExistTableMappingDomain;
import com.sh.data.engine.domain.integration.offline.model.domain.OfflineTaskExistTableMappingQueryDomain;
import com.sh.data.engine.domain.integration.offline.service.OfflineSyncService;
import com.sh.data.engine.domain.shims.db.model.PreviewDataDomain;
import com.sh.data.engine.domain.shims.db.model.TableInfoDomain;
import com.sh.data.engine.domain.util.ConvertUtil;
import com.sh.data.engine.repository.dao.dataasset.entity.TblPropEntity;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * @author: mengzheng.mhc
 * @date: 2024/7/12 10:08
 */
@Slf4j
@Service
public class OfflineDevSyncApplicationService {

    @Autowired
    private OfflineDevMenuNodeService offlineDevMenuNodeService;

    @Autowired
    private DatadevJobService datadevJobService;

    @Autowired
    private DataSourceService dataSourceService;

    @Autowired
    private TblPropService tblPropService;

    @Autowired
    private OfflineSyncService offlineSyncService;

    @Autowired
    private OfflineDevSyncResponseMapper offlineDevSyncResponseMapper;

    public boolean saveOfflineSyncTask(OfflineDevSyncRequest request) {
        Long projectId = ServletUtils.getProjectId();
        String userId = UserContext.getUserId();

        OfflineDevSyncDomain offlineSyncDomain = Convert.convert(OfflineDevSyncDomain.class, request);
        offlineSyncDomain.setProjectId(projectId);
        offlineSyncDomain.setCreatorId(userId);
        offlineDevMenuNodeService.saveOrUpdateOfflineSyncTask(offlineSyncDomain);
        return true;
    }

    public OfflineDevSyncResponse getOfflineSyncTask(Long nodeId) {
        OfflineDevSyncDomain offlineDevSyncDomain =
            offlineDevMenuNodeService.getOfflineDevSyncDomainByNodeId(nodeId);
        return offlineDevSyncResponseMapper.map(offlineDevSyncDomain);
    }

    public OfflineDevPreviewDataResponse previewData(Long dsId, String tableName) {
        PreviewDataDomain previewDataDomain = dataSourceService.previewData(dsId, tableName);
        return ConvertUtil.copyProperties(previewDataDomain, OfflineDevPreviewDataResponse.class);
    }

    public String getCreateTableSql(Long dsId, String tableName, Long targetDsId, String schema, int infoCase) {
        return dataSourceService.getCreateTableSql(dsId, tableName, targetDsId, schema, infoCase);
    }

    public OfflineDevCreateTableResponse executeCreateTableSql(Long dsId, String scripts, String dataSecretId) {
        DataSourceCreateTableDomain dataSourceCreateTableDomain =
            dataSourceService.executeCreateTableSql(dsId, scripts);
        OfflineDevCreateTableResponse offlineDevCreateTableResponse =
            ConvertUtil.copyProperties(
                dataSourceCreateTableDomain, OfflineDevCreateTableResponse.class);

        Long projectId = ServletUtils.getProjectId();
        TblPropEntity tblPropEntity = new TblPropEntity();
        tblPropEntity.setProjectId(projectId);
        tblPropEntity.setSchema(dataSourceCreateTableDomain.getSchema());
        tblPropEntity.setTblId(tblPropService.generateTblId(projectId));
        tblPropEntity.setTableName(dataSourceCreateTableDomain.getOnlyTableName());
        tblPropEntity.setLifecycle(-1);
        tblPropEntity.setTblType(TableInfoDomain.TblType.MANAGED_TABLE.name());
        tblPropEntity.setRowState(1);
        tblPropService.save(tblPropEntity);

        return offlineDevCreateTableResponse;
    }

    public List<OfflineSyncDatabaseResponse> getOfflineSyncDatabases(String dsId, Integer direction) {
        List<OfflineSyncDatabaseDomain> offlineTaskDatabaseDomains =
            offlineSyncService.getOfflineSyncDatabases(direction, dsId);
        return ConvertUtil.copyProperties(offlineTaskDatabaseDomains, OfflineSyncDatabaseResponse.class);
    }

    public List<OfflineSyncTablesResponse> getTables(Long dsId, String schema, Integer direction) {
        List<OfflineSyncTableDomain> tableDomains =
            offlineSyncService.getOfflineSyncTables(direction, dsId, schema);
        return Convert.toList(OfflineSyncTablesResponse.class, tableDomains);
    }

    public List<String> getSchemas(Long dsId, String dsType) {
        return dataSourceService.getDataSourceSchema(dsId, dsType);
    }

    public OfflineTaskExistTableMappingResponse getExistTablesMappings(OfflineTaskExistTableMappingRequest request) {
        OfflineTaskExistTableMappingQueryDomain queryDomain =
            Convert.convert(OfflineTaskExistTableMappingQueryDomain.class, request);
        OfflineTaskExistTableMappingDomain tableMappingDomain =
            this.offlineSyncService.getExistTablesMappings(queryDomain);
        return Convert.convert(OfflineTaskExistTableMappingResponse.class, tableMappingDomain);
    }

    public boolean sapTableExist(Long dsId, String tableName) {
        return dataSourceService.tableExist(dsId, tableName);
    }

    public Long startOfflineSyncTask(Long nodeId) {
        Long projectId = ServletUtils.getProjectId();
        int execType = 0;
        String userId = UserContext.getUserId();
        return datadevJobService.startOfflineSyncTask(nodeId, execType, projectId, userId);
    }
}
